﻿/*
 * This file is part of MonoStrategy.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://monostrategy.codeplex.com/
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Globalization;
using System.Drawing;
using System.IO;
using System.ComponentModel;
using System.Drawing.Imaging;
using MonoStrategy.RenderSystem;

namespace MonoStrategy
{
    /// <summary>
    /// Interaction logic for AnimLibraryTab.xaml
    /// </summary>
    public partial class AnimLibraryTab : UserControl
    {
        private RenderableAnimationClass m_RenderableClass = null;
        private TerrainDefinition m_Terrain;
        private Boolean m_AnimIsMouseDown = false;
        private RenderableAnimationClass m_RenderableResource;
        private RuntimeBuildingEditor m_BuildingEditor;
        private System.Diagnostics.Stopwatch m_Watch = new System.Diagnostics.Stopwatch();

        private void InitializeAnimationPlayer()
        {
            Program.Config = XMLConfig.Load("./MonoStrategy.config.xml");

            var playerContainer = new System.Windows.Forms.ContainerControl();

            m_AnimationPlayer = GLRenderer.CreateControl(playerContainer);
            m_Terrain = new TerrainDefinitionEditor();
            m_Watch.Start();

            System.Threading.ThreadPool.QueueUserWorkItem((unused) =>
            {
                m_AnimationPlayer.AttachTerrain(m_Terrain);
                m_AnimationPlayer.TerrainRenderer.PrecisionTimerCallback += () => { return m_Watch.ElapsedMilliseconds; };
                m_AnimationPlayer.EnableTerrainRendering = true;

                m_AnimationPlayer.TerrainRenderer.OnMouseGridMove += (sender, grid) =>
                {
                    if (!m_AnimIsMouseDown)
                        return;

                    RenderableAnimationClass renderable = m_RenderableClass;

                    if (renderable != null)
                    {
                        if (RADIO_AnimMove.IsChecked.Value)
                            m_BuildingEditor.SetPosition(grid);
                    }

                    if (RADIO_AnimResource.IsChecked.Value)
                    {
                        m_RenderableResource.Position = CyclePoint.FromGrid(grid);
                    }
                };
            });

            m_AnimationPlayer.OnMouseDown += (sender, btn) =>
            {
                m_AnimIsMouseDown = true;

                if (btn == (int)OpenTK.Input.MouseButton.Middle)
                {
                    m_AnimationPlayer.TerrainRenderer.IsBuildingGridVisible = false;

                    if (RADIO_AnimZPlane.IsChecked.Value)
                    {
                        foreach (var spot in m_BuildingEditor.GetSurroundingSettlersSpots())
                        {
                            AnimationLibrary.Instance.ForcePositionShift = true;

                            RenderableAnimationClass anim = m_AnimationPlayer.TerrainRenderer.CreateAnimation("SettlerWalking", new PositionTracker(), 1);

                            AnimationLibrary.Instance.ForcePositionShift = false;

                            m_BuildingEditor.SurroundingSettlers.Add(anim);

                            anim.Position = CyclePoint.FromGrid(
                                spot.X + m_BuildingEditor.Position.X,
                                spot.Y + m_BuildingEditor.Position.Y);

                            anim.Play("FrozenAngle_045");
                        }
                    }

                    if (RADIO_AnimBuild.IsChecked.Value)
                    {
                        foreach (var spot in m_BuildingEditor.GetSurroundingBuildingsSpots())
                        {
                            RenderableAnimationClass anim = m_AnimationPlayer.TerrainRenderer.CreateAnimation(m_BuildingEditor.Class, new PositionTracker(), 1);

                            m_BuildingEditor.SurroundingBuildings.Add(anim);

                            anim.Position = CyclePoint.FromGrid(spot);
                        }
                    }
                }
            };
            m_AnimationPlayer.OnMouseUp += (sender, btn) =>
            {
                var gridPos = m_AnimationPlayer.TerrainRenderer.GridXY;
                var relPos = new Point(gridPos.X - m_BuildingEditor.Position.X, gridPos.Y - m_BuildingEditor.Position.Y);

                m_AnimIsMouseDown = false;

                if (btn == (int)OpenTK.Input.MouseButton.Right)
                {
                    if (RADIO_AnimResource.IsChecked.Value)
                    {
                        // add resource
                        m_BuildingEditor.ResourceStacks.Add(m_RenderableResource);
                        m_RenderableResource = null;

                        RADIO_AnimMove.IsChecked = true;
                    }

                    if (RADIO_AnimZPlane.IsChecked.Value)
                        m_BuildingEditor.GroundPlane.Remove(relPos);

                    if (RADIO_AnimBuild.IsChecked.Value)
                        m_BuildingEditor.ReservedPlane.Remove(relPos);
                }
                else if (btn == (int)OpenTK.Input.MouseButton.Left)
                {
                    if (RADIO_AnimZPlane.IsChecked.Value)
                    {
                        if (!m_BuildingEditor.GroundPlane.Contains(relPos))
                            m_BuildingEditor.GroundPlane.Add(relPos);
                    }

                    if (RADIO_AnimBuild.IsChecked.Value)
                    {
                        if (!m_BuildingEditor.ReservedPlane.Contains(relPos))
                            m_BuildingEditor.ReservedPlane.Add(relPos);
                    }
                }
                else if (btn == (int)OpenTK.Input.MouseButton.Middle)
                {
                    if (RADIO_AnimZPlane.IsChecked.Value)
                    {
                        m_AnimationPlayer.TerrainRenderer.IsBuildingGridVisible = true;

                        ClearRendableList(m_BuildingEditor.SurroundingSettlers);
                    }

                    if (RADIO_AnimBuild.IsChecked.Value)
                    {
                        m_AnimationPlayer.TerrainRenderer.IsBuildingGridVisible = true;

                        ClearRendableList(m_BuildingEditor.SurroundingBuildings);
                    }

                    if (RADIO_AnimResource.IsChecked.Value)
                    {
                        ClearRendableList(m_BuildingEditor.ResourceStacks);
                    }
                }
            };

            HOST_AnimationPlayer.Child = playerContainer;
        }

        private void UpdateAnimationPlayer()
        {
            var animClass = TCurrentClass;
            var animSet = TCurrentSet;

            if((m_RenderableClass != null) && (animClass != m_RenderableClass.Class))
            {
                if(m_BuildingEditor != null)
                    m_BuildingEditor.Save();

                // remove previous renderable
                m_AnimationPlayer.TerrainRenderer.RemoveVisual(m_RenderableClass);

                m_RenderableClass = null;
            }

            if (m_RenderableClass != null)
            {
                // change animation set
                if (animSet == null)
                    m_RenderableClass.Stop();
                else
                    m_RenderableClass.Play(animSet);
            }
            else
            {
                if (animClass == null)
                    return;

                // create new class renderer
                m_RenderableClass = m_AnimationPlayer.TerrainRenderer.CreateAnimation(animClass, new PositionTracker(), 1);

                 if (animSet != null)
                     m_RenderableClass.Play(animSet);

                 m_AnimationPlayer.TerrainRenderer.ScreenXY = new PointDouble(0, 0);
                 InitBuildingEditor(m_RenderableClass);
            }

            if (RADIO_AnimResource.IsChecked.Value)
            {
                Resource resource = (Resource)COMBO_AnimResource.SelectedValue;

                if (m_RenderableResource == null)
                {
                    m_RenderableResource = m_AnimationPlayer.TerrainRenderer.CreateAnimation("ResourceStacks", new PositionTracker(), 1);
                    m_RenderableResource.FrozenFrameIndex = 7;
                }

                m_RenderableResource.Play(resource.ToString());
            }
            else
            {
                if(m_RenderableResource != null)
                    m_AnimationPlayer.TerrainRenderer.RemoveVisual(m_RenderableResource);

                m_RenderableResource = null;
            }

            if (RADIO_AnimBuild.IsChecked.Value || RADIO_AnimZPlane.IsChecked.Value)
            {
                m_AnimationPlayer.TerrainRenderer.IsBuildingGridVisible = true;
            }
            else
            {
                m_AnimationPlayer.TerrainRenderer.IsBuildingGridVisible = false;
            }

            if (m_BuildingEditor != null)
            {
                m_BuildingEditor.ShowBuildings = RADIO_AnimBuild.IsChecked.Value;
                m_BuildingEditor.ShowSettlers = RADIO_AnimZPlane.IsChecked.Value;
            }
        }

        private void ClearRendableList(List<RenderableAnimationClass> inList)
        {
            foreach (var stack in inList)
            {
                m_AnimationPlayer.TerrainRenderer.RemoveVisual(stack);
            }

            inList.Clear();
        }

        private void InitBuildingEditor(RenderableAnimationClass inClass)
        {
            if (m_BuildingEditor != null)
            {
                ClearRendableList(m_BuildingEditor.ResourceStacks);
            }

            m_BuildingEditor = new RuntimeBuildingEditor(inClass, m_Terrain);
            m_Terrain.ResetBuildingGrid(m_BuildingEditor.Config);

            foreach(var stack in inClass.Class.ResourceStacks)
            {
                RenderableAnimationClass anim = m_AnimationPlayer.TerrainRenderer.CreateAnimation("ResourceStacks", new PositionTracker()
                {
                    Position = CyclePoint.FromGrid(stack.Position),
                }, 1);

                anim.FrozenFrameIndex = 7;
                anim.Play(stack.Resource.ToString());

                m_BuildingEditor.ResourceStacks.Add(anim);
            }
        }
    }
}
